[% setvar title Replace localtime() and gmtime() with date() and utcdate() %]
<div id="archive-notice">
    <h3>This file is part of the Perl 6 Archive</h3>
    <p>To see what is currently happening visit <a href="http://www.perl6.org/">http://www.perl6.org/</a></p>
</div>
<div class='pod'>
<a name='TITLE'></a><h1>TITLE</h1>
<p>Replace localtime() and gmtime() with date() and utcdate()</p>
<a name='VERSION'></a><h1>VERSION</h1>
<pre>  Maintainer: Nathan Wiger &lt;<a href='mailto:nate@wiger.org'>nate@wiger.org</a>&gt;
  Date: 5 Aug 2000
  Last Modified: 25 Sep 2000
  Mailing List: <a href='mailto:perl6-language-datetime@perl.org'>perl6-language-datetime@perl.org</a>
  Number: 48
  Version: 4
  Status: Frozen
  Requires: RFC 21, RFC 159</pre>
<a name='ABSTRACT'></a><h1>ABSTRACT</h1>
<p>Currently, Perl uses the C library <code>localtime()</code> and <code>gmtime()</code>
functions for date access. However, because of many problems, these
should be replaced with two new functions, <code>date()</code> and
<code>utcdate()</code> that will be called as follows:</p>
<pre>   $object  =  date;     # object with accessor functions (new)
   print &quot;$object&quot;;      # scalar ctime date, same as current
   @array   =  date;     # list of date/time values (new order)
   %hash    =  date;     # hash of date/time values (new)</pre>
<p>The new <code>date()</code> function will return time adjusted for the local
timezone. The <code>utcdate()</code> function will return time in UTC. In a scalar
context, an object is always returned. This object is then converted to
a string on-demand via <b>RFC 159: True Polymorphic Objects</b>.</p>
<a name='NOTES ON FREEZE'></a><h1>NOTES ON FREEZE</h1>
<p>Everyone felt pretty good about this, I think. The only thing we'd all
probably like to see is one single <code>date</code> function, but unfortunately
dealing with timezone specifications is an extraordinarily difficult
issue.</p>
<a name='DESCRIPTION'></a><h1>DESCRIPTION</h1>
<a name='Overview'></a><h2>Overview</h2>
<p>In the past, Perl has provided access to date and time information
through the C library <code>localtime()</code> and <code>gmtime()</code> functions.
Unfortunately, these functions have several &quot;really bad things&quot; about
them:</p>
<pre>   1. some values are 0-indexed while others are 1-indexed
   2. they return massive lists as their only interface
   3. minute and second values aren't 0-padded
   4. the year has to have 1900 added to it to be correct.</pre>
<p>While some of these are perhaps understandable, that last one just plain
doesn't make <i>any</i> sense. :-)</p>
<p>With Perl 6 we have the chance to fix this. While some have suggested
merely changing what <code>localtime()</code> and <code>gmtime()</code> return, this is a
bad idea because:</p>
<pre>   1. Many Perl scripts already use it
   2. Many C programmers are familiar with its stupidity</pre>
<p>As such, we should replace these functions with versions that work the
way that we want them to. The new names will indicate that these are
&quot;not the same old time functions&quot;, and that you'd better read the docs.</p>
<a name='Proposed Syntax'></a><h2>Proposed Syntax</h2>
<p>The new syntax of <code>date()</code> and <code>utcdate</code> is proposed as:</p>
<pre>   $|@|%return  =  date [ $time ], [ $format ];</pre>
<p>If <code>$time</code> is not specified, then the current return value from
<code>time()</code> is used (just like <code>localtime()</code>).</p>
<p>The optional <code>$format</code> affects the format of the date returned. By
default, a ctime-formatted string is used, like <code>localtime</code>. However,
any POSIX-compatible format can be passed in, in which case the date
returned in a scalar context is formatted accordingly.</p>
<p><i>Actually</i>, what it does is call the object function <code>setformat()</code>
with the format, which in turn determines what calls to the <code>date()</code>
object member function look like. Since the <code>date()</code> member function
is what is output when the date object is stringified, this is how
the scalar date appears to change. See below.</p>
<p>The <code>$format</code> specifier is the same one used in <code>POSIX strftime()</code>,
allowing complete date formatting with having to import the <code>POSIX</code>
module.</p>
<p>Depending on the context within which <code>date()</code> is called, many
different things are returned:</p>
<pre>   # Get some various local date stuff
   $object  =  date;            # scalar ctime date, same as now
   $object  =  date time, '%m/%d/%Y';  # set date MM/DD/YYYY format
   $object  =  date $time;      # relative to time $time
   print &quot;$object&quot;;             # scalar date string per format   

   @array   =  date;            # array of date/time values
   %hash    =  date;            # hash of values

   # Access UTC information
   $object  =  utcdate time, '%H:%M'; # return time in UTC</pre>
<a name='Return Values'></a><h2>Return Values</h2>
<p>The return values are dependent on the context within which <code>date()</code> is
called. For all contexts, the following are the values and their ranges:</p>
<pre>   $hour  =  0 .. 23  
   $min   =  00 .. 59   # 0-padded
   $sec   =  00 .. 59   # 0-padded
   $fsec  =  0 .. 1     # fractional seconds per hw clock

   $month =  1 .. 12    # hooray!
   $day   =  1 .. 31 
   $year  =  1 .. 9999  # 4-digit! 

   $wday  =  1 .. 7     # 1 == *Monday*, POSIX-compliant
   $yday  =  1 .. 366

   $isdst =  1 or undef;  # daylight savings?
   $isgmt =  1 or undef;  # is GMT?
   $tz    =  [depends on your system, this &quot;eats people&quot;]</pre>
<p>For those who are concerned about $wday not being 0-indexed, please see
below under the object methods. Remember you can always use formats to
return what you want as well.</p>
<a name='STRING Context'></a><h3>STRING Context</h3>
<p>In a <code>STRING</code> (not scalar) context, a single ctime-formatted date
string is returned, consistent with the current usage of <code>localtime()</code>.
If the optional <code>$format</code> is included, this format is used to change
the string accordingly.</p>
<p>In order to emulate a string, a call is made to the date object's
builtin <code>STRING</code> function, which prints out a date string. This is per
RFC 159: True Polymorphic Objects.</p>
<a name='LIST, ARRAY, and ARRAYREF Contexts'></a><h3>LIST, ARRAY, and ARRAYREF Contexts</h3>
<p>A list of date/time values is returned. The ordering and format of these
values has been radically changed to reflect what most of us probably
view as &quot;ordinary&quot;:</p>
<pre>  ($year, $month, $day, $hour, $min, $sec, $tz) = date;</pre>
<p>You'll note that many elements, such as $isdst, $wday, and $yday have
been dropped from the list return context. This is to encourage the use
of more sane contexts, such as object and hash/hashrefs for complex
operations.</p>
<p>This ordering follows the predictable pattern of being in increasing
granularity and so should be easy to remember. Just think of a
computer-esque decending timestamp:</p>
<pre>   2000/11/4 12:03:09</pre>
<p>Note that the month, day, and year are not 0-padded. If you want a
padded date, perhaps as a file backup suffix, you'll have to say:</p>
<pre>   $backup_suffix = date time, '%Y%m%d%H%M%S';</pre>
<p>Which would return something like &quot;20001104120309&quot; (actually, it would
return an object with the appropriate default format so that, when
stringified, it would yield the above result).</p>
<p>These same values can be retrieved when referred to as an arrayref,
so these two:</p>
<pre>    $month = (date)[1];
    $month = date-&gt;[1];</pre>
<p>Have the same effect. Now, of course, if you want specific values you
should be using...</p>
<a name='HASH and HASHREF Contexts'></a><h3>HASH and HASHREF Contexts</h3>
<p>A hash of values is returned. These are named the same as the variables
above. So,</p>
<pre>   %date = date;</pre>
<p>Would return a hash with these values (assuming the same date shown
above):</p>
<pre>   $date{year}  = 2000;
   $date{month} = 11; 
   $date{day}   = 4;   
   $date{hour}  = 12;
   $date{min}   = 03; 
   $date{sec}   = 09;
   $date{fsec}  = 0.4291;  # up to hw resolution
   $date{wday}  = 2; 
   $date{yday}  = 331;
   $date{tz}    = 'PST';   # or maybe 'US/Pacific', or ...
   $date{isdst} = undef;</pre>
<p>These same values will be available via a HASHREF, so again these:</p>
<pre>   $month = ${(date)}{month};
   $month = date-&gt;{month};</pre>
<p>Will work the same (at least, I think that first one's right per RFC
21)...</p>
<a name='SCALAR Context'></a><h3>SCALAR Context</h3>
<p>In an <code>SCALAR</code> context, an object is returned. This is somewhat adapted
from <code>Time::Object</code> and Larry's own comments, but with several key
differences. The ones noted with * are incompatible with <code>Time::Object</code></p>
<pre>   $t = date;            # create date object

   &quot;$t&quot;                  # calls $t-&gt;STRING, same as $t-&gt;date
   $t++                  # calls $t-&gt;NUMBER, same as $t-&gt;time

   $t-&gt;year
   $t-&gt;month             # *
   $t-&gt;day               # *
   $t-&gt;hour
   $t-&gt;min
   $t-&gt;sec
   $t-&gt;fsec              # fractional seconds
   $t-&gt;fsecres           # fsec resolution (num of digits for hw)
   $t-&gt;wday              # *
   $t-&gt;yday
   $t-&gt;isdst
   $t-&gt;tz
   $t-&gt;tzoffset          # timezone offset in seconds ($t-&gt;tzsec?)
   $t-&gt;time              # number of seconds since the epoch, so it
                         # contains what time() was when you called
                         # date() </pre>
<p>These functions are object-specific:</p>
<pre>   $t-&gt;date              # Tue Feb 29 01:23:45 2000 (depending on 
                         # default format set by $t-&gt;setformat)

   $t-&gt;date(FORMAT)      # Return a temporarily-modified date,
                         # without affecting the default format.

   $t-&gt;setformat(FORMAT) # Set default format which determines what
                         # calls to $t-&gt;date (stringified $t) look like
                         # This is called on object creation</pre>
<p>These functions are separate for an important reason:</p>
<pre>   print $t-&gt;date('%H:%M');    # prints out hours and minutes
   print &quot;$t&quot;;                 # without touching default format

   $oldfmt = $t-&gt;setformat('%Y');  # sets POSIX fmt string
   print &quot;$t&quot;;                 # which affects the default format</pre>
<p>The <code>set</code> prefix was explicitly added to make it obvious this sets
something (rather than just formatting the date like strftime).</p>
<p>Many functions were deemed of dubious quality/excessive bloat and were
all removed from the RFC. Note that you can get to any extra data by
calling $t-&gt;date with the correct format. So,</p>
<pre>   print $t-&gt;date('%w');</pre>
<p>Will give you the weekday numbered starting with 0 == Sunday.</p>
<a name='Date Arithmetic'></a><h2>Date Arithmetic</h2>
<p>You'll note that simple date arithmetic is available via polymorphic
overloading in numeric contexts. For example:</p>
<pre>   $t1 = date;
   $t2 = date;
   $diff = $t2 - $t1;   # calls -&gt;NUMBER (-&gt;time) on both</pre>
<p>The result will simply be the difference in seconds between the two, in
simple scalar form (i.e., &quot;15&quot;). The result is designed to be the same
as if you had created $t1 and $t2 based on the output of time(), without
requiring you to put extra calls in your code. To simply increment the
date by one second each loop, do:</p>
<pre>   $d = date;
   while (stuff()) {
      $d++;
   }</pre>
<p>This gives the basis from which more complex date arithmetic can be
derived, which should be in a module.</p>
<a name='IMPLEMENTATION'></a><h1>IMPLEMENTATION</h1>
<p>Slash and burn <code>localtime()</code> and <code>gmtime()</code>. Actually, we should
probably move them to <code>Time::Local</code> or some other place and keep them
available, since some people like pain.</p>
<p>Nonetheless, <code>localtime()</code> and <code>gmtime()</code> SHOULD BE REMOVED FROM CORE
and placed in a module. Perl 6 should support ONE date/time interface
natively.</p>
<p>Extensive date calculations, including reverse date calculations, should
be left to an external module.</p>
<p>I am currently working on a Perl 5 prototype and will announce it to the
list when it is completed.</p>
<a name='ACKNOWLEDGEMENTS'></a><h1>ACKNOWLEDGEMENTS</h1>
<p>Jonathan Scott Duff, Tim Jenness, Johan Vromans, Buddha Buck, and lots
of other members of perl6-language for great feedback.</p>
<p>Russ Allbery and John Tobey for suggesting parts to slice-and-dice.</p>
<a name='REFERENCES'></a><h1>REFERENCES</h1>
<p>Larry Wall's post of 8 Jan 2000 on deprecating localtime:
<a href='http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2000-01/msg00241.html' target='_blank'>www.xray.mpe.mpg.de</a></p>
<p>RFC 159: True Polymorphic Objects</p>
<p>RFC 21: Replace wantarray() with a generic want() function</p>
<p>RFC 37: Positional Return Lists Considered Harmful</p>
<p>Matt Sergeant's great Time::Object CPAN module</p>
<p><a href='http://www.jach.hawaii.edu/JACpublic/stardocs/sun67.htx/node217.html' target='_blank'>www.jach.hawaii.edu</a></p>
<p><a href='http://tycho.usno.navy.mil/systime.html' target='_blank'>tycho.usno.navy.mil</a></p>
</div>
